<?

class DisOrderException extends Exception{}
class InterFaceException extends Exception{}
class MsgException extends Exception{}

/**
 *下单基类
 *通过调用order()完成下单流程
 */
class OrderSubmit{

    /**
     *票付通内部接口对象
     *@var object
     */
    public $s;

    /**
     *产品下单信息
     *@var array
     */
    public $option;//订单参数

    /**
     *产品信息类ProductInfo对象，查询产品信息和分销价格
     *@var object
     */
    public $p;//产品

    /**
     *会员类Member对象,查询账户余额
     *@var object
     */
    public $m;//分销商

    /**
     *是否零售
     *@var int 0不零售1零售
     */
    protected $sale;

    /**
     *下单方式
     *@var int 0正常下单1普通用户下单按零售价
     */
    protected $ordermode;

    /**
     *@param object $s 票付通内部接口对象
     *@param object $p 产品ProductInfo对象
     *@param object $m 会员Member对象
     *@param int $ordermode 下单方式
     *@param int $sale 是否零售
     */
    public function __construct(SoapClient $s, ProductInfo $p, Member $m,$ordermode, $sale){
        $this->s=$s;
        $this->p=$p;
        $this->m=$m;
        $this->sale = $sale;
        $this->ordermode=$ordermode;
    }
    // 计算身份证校验码，根据国家标准GB 11643-1999
    public function idcard_verify_number($idcard_base){
        if(strlen($idcard_base)!=17){
            return false;
        }
        //加权因子
        $factor=array(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2);

        //效验码对应值
        $verify_number_list=array('1','0','X','9','8','7','6','5','4','3','2');

        $checksum=0;
        for($i=0;$i<strlen($idcard_base);$i++){
            $checksum += substr($idcard_base,$i,1) * $factor[$i];
        }

        $mod=$checksum % 11;
        $verify_number=$verify_number_list[$mod];

        return $verify_number;
    }

    // 将15位身份证升级到18位
    public function idcard_15to18($idcard){
        if(strlen($idcard)!=15){
            return false;
        }
        else{//如果身份证顺序码是996 997 998 999，这些是为百岁以上老人的特殊编码
            if(array_search(substr($idcard,12,3),array('996','997','998','999'))!==false){
                $idcard=substr($idcard,0,6).'18'.substr($idcard,6,9);
            }else{
                $idcard=substr($idcard,0,6).'19'.substr($idcard,6,9);
            }
        }
        $idcard=$idcard.($this->idcard_verify_number($idcard));

        return $idcard;
    }

    // 18位身份证校验码有效性检查
    public function idcard_checksum18($idcard){
        if(strlen($idcard)!=18){ return false; }
        $idcard_base=substr($idcard,0,17);
        if($this->idcard_verify_number($idcard_base)!=strtoupper(substr($idcard,17,1))){
            return false;
        }
        else{
            return true;
        }
    }
    public function setSaleMode()
    {
        $this->sale = 1;
    }
    /**
     *@param array $option 下单参数
     *@return int $r 成功返回主6位数订单号，失败返回-100
     */
    /**
     *
     *
     * @param $option
     * @param int $aid
     * @return array
     * @throws DisOrderException
     */
    public function order($option, $aid = 0, $debug = false)
    {
        $s = $this->s;
        $this->option = $option;
        $member = $this->m->memberID;
        $pid = $this->p->pid;

        $begintime = $option['begintime'];
        $ordername = $option['ordername'];
        $ordertel = $option['ordertel'];
        $contacttel = $option['contacttel'];
        $tnum = $option['tnum'];
        $remoteorder = $option['remoteorder'];
        $paymode = $option['paymode'];
        //订单类型，normalOrder=>普通订单，linkOrder=>联票订单，packageOrder=>套票订单
        $orderType = 'normalOrder';
        $p_info = $this->p->pInfo();

//        $ptitle = $p_info['ltitle'].$p_info['ttitle'];
        $endtime = ($p_info['delaydays'] - 1) < 0 ? 0 : ($p_info['delaydays'] - 1);
        $time = strtotime($begintime) + $endtime * 24 * 3600;
        $endtime = date("Y-m-d", $time);
        $begintime .= " 00:00:00";
        $endtime .= " 23:59:59";

        /*产品预订检查*/
        $totalMoney = 0;

        $account = $option['account'] ? $option['account'] : '';
        // 新接口获取
        $tprice = $this->p->tPrice_n($this->sale, $begintime, $aid, '', $account);
        if ($debug) {
            echo $this->sale . '---';
            echo $tprice;
            exit;
        }
        if (is_array($tprice)) {
            throw new DisOrderException($tprice['msg']);
        }
        $totalTprice = $tprice * $tnum;
        $totalMoney += $totalTprice;

        $pcode = 0;
        $ordermode = isset($option['ordermode']) ?
            $option['ordermode'] : $this->ordermode;


        if ($p_info['p_type'] == "B") { /*线路产品额外信息*/
            $playdateStr = explode("-", substr($begintime, 0, 10));
            $playdateStr = substr($playdateStr[0], 2, 2) . $playdateStr[1] . $playdateStr[2];
            $series = preg_replace('/{fck_date}/', $playdateStr, $p_info['series_model']); //团号
            $assembly = abs($_REQUEST['assembly']); //集合地点
        }
//        $proInfos=array();
        $c_infos = array();
        if ($p_info['p_type'] == "C") { //酒店按联票产品下单
            $leavetime = $option['leavetime'];
            $days = ceil((strtotime($leavetime) - strtotime($begintime)) / 24 / 3600);
            $orderType = $days > 1 ? 'linkOrder' : 'normalOrder';
            for ($n = 1; $n < $days; $n++) {
                try {
                    $date = date("Y-m-d", strtotime($begintime) + 3600 * 24 * $n);
                    $starttime = $date . " 00:00:00";
                    // $c_tprice=$cpro->tPrice($member,$begintime,$this->sale);
                    $c_tprice = $this->p->tPrice_n($this->sale, $starttime, $aid,
                        null, $account);
                    // 新接口
                    $c_tnum = $tnum;
                    $endtime = $date . " 23:59:59";
                    $c_infos[] = array("member" => $member,
                        "tprice" => $c_tprice, "tnum" => $c_tnum,
                        "ltitle" => $p_info['ltitle'],
                        "ttitle" => $p_info['ttitle'],
                        "pid" => $p_info['pid'],
                        "lid" => $p_info['lid'],
                        "tid" => $p_info['tid'],
                        "begintime" => $starttime,
                        "endtime" => $date . " 23:59:59",
                        "storage" => $p_info['storage'],
                        "storage_open" => $p_info['storage_open'],
                        "salerid" => $p_info['salerid'],
                        "ordername" => $ordername,
                        "ordertel" => $ordertel,
                        "paymode" => $paymode,
                        "ordermode" => $ordermode,
                        "apply_did" => $p_info['apply_did'],
                        "sapply_did" => $p_info['sapply_did'],
                        "contacttel" => $option['contacttel'],
                    );
                    $totalMoney += $c_tprice * $c_tnum;
                } catch (Exception $e) {
                }
            }
        } elseif ($p_info['p_type'] == "F") { //套票产品
            $pcode = 1;
            $orderType = 'packageOrder';
            //套票判定 Author:CGP
            $bt = substr($begintime, 0, 10);
            $chk_ret = \pft\Prod\Sale::PackageTicketCheck($s, $pid, $member, $aid,
                $bt, $tnum);
            if ($chk_ret['code'] !== 200) {
                $msg = $chk_ret['code'] > 908 ? "子票【{$chk_ret['pid']}】" : '';
                throw new DisOrderException($msg . $chk_ret['msg']);
            }
        } else {
            /*查看是否存在联票产品，存在的话记录联票产品下单信息*/
            foreach ((array)$option['c_pids'] as $c_pid => $c_tnum) {
                if ($c_tnum > 0) {
                    $orderType = 'linkOrder';
                    $c_pid = abs($c_pid);
                    $c_about = $this->p->pInfo($c_pid);
                    // $c_tprice = $this->p->tPrice($member, $begintime, $this->sale, $c_pid);
                    $c_tprice = $this->p->tPrice_n($this->sale, $begintime, $aid,
                        $c_pid, $account);
                    // 新接口
                    $c_infos[] = array(
                        "member" => $member,
                        "tprice" => $c_tprice,
                        "tnum" => $c_tnum,
                        "ltitle" => $c_about['ltitle'],
                        "ttitle" => $c_about['ttitle'],
                        "pid" => $c_pid,
                        "lid" => $c_about['lid'],
                        "tid" => $c_about['tid'],
                        "begintime" => $begintime,
                        "endtime" => $endtime,
                        "storage" => $c_about['storage'],
                        "storage_open" => $c_about['storage_open'],
                        "salerid" => $c_about['salerid'],
                        "ordername" => $ordername,
                        "ordertel" => $ordertel,
                        "paymode" => $paymode,
                        "ordermode" => $ordermode,
                        "apply_did" => $c_about['apply_did'],
                        "sapply_did" => $c_about['sapply_did'],
                        "contacttel" => $option['contacttel'],
                        "sfz" => $option['sfz'],
                    );
                    $totalMoney += $c_tprice * $c_tnum;
                }
            }
        }

        $smsSendAfterOrder = 0; //下单后发送短信0不发送1发送
        $smsSendWithOrder = 1; //下单并发送短信0发送1不发送
        $isLnkOrder = count($c_infos); //是否联票订单
        $proInfos = $isLnkOrder ? $c_infos : array(); //联票购买

        if ($paymode == 1 || $p_info['sendVoucher'] == 1) {
            //未支付或特殊设置不发送短信
        } elseif ($isLnkOrder || $p_info['p_type'] == 'C') {
            //联票订单或酒店订单，下单后发送短信
            $smsSendAfterOrder = 1;
        } else {
            //跟随订单一起发送短信
            $smsSendWithOrder = 0;
        }

        $proInfos[] = array(
            "member" => $member,
            "tprice" => $tprice,
            "tnum" => $tnum,
            "ltitle" => $p_info['ltitle'],
            "ttitle" => $p_info['ttitle'],
            "pid" => $p_info['pid'],
            "tid" => $p_info['tid'],
            "begintime" => $begintime,
            "endtime" => $endtime,
            "storage" => $p_info['storage'],
            "storage_open" => $p_info['storage_open'],
            "sapply_did" => $p_info['sapply_did']
        );

        $this->orderCheck($option, $p_info); //预订判定
        //TODO::如果是零售（散客购买),就不判断购买权限，反正都是用零售价
        if (!$this->sale) {
            $this->authCheck($proInfos, $aid); //购买权限判定
        }

        $this->storageCheck($proInfos); //库存判定
        $this->payCheck($totalMoney); //金额判定

        $r = $s->Group_Order_Submit($member, $p_info['lid'], $p_info['tid'],
            $begintime, $endtime, $tprice, $tnum, $totalTprice, $ordername,
            $ordertel, "$contacttel", $p_info['salerid'], $p_info['sapply_did'],
            $paymode, $ordermode, "$remoteorder", "$assembly", "$series",
            $smsSendWithOrder, 0, $pcode, $option['sfz']);

        $sendRut = '';
        if ($r >= 100000) {
            /*附属产品下单*/
            if ($isLnkOrder) {
                $this->subOrder($c_infos, $r);
            }
            //下单后发送短信
            if ($smsSendAfterOrder == 1) {
                include '/var/www/html/new/d/class/OrderSmsManual.class.php';
                $smsManual = new \PFT\SMS\OrderSmsManual($s);
                $smsManual->SetParam($ordertel, $aid, $member, $p_info['tid'],
                    $pid, $r, $p_info['lid']);
                $sms_ret = $smsManual->Send($p_info['ltitle'] . $p_info['ttitle'],
                    $tnum, $begintime, $endtime, $p_info['p_type']);
                if ($sms_ret != 100) {
                    self::log_result("短信发送失败|订单号[$r]|错误代码[{$sms_ret}]", '/var/www/html/new/d/logs/debug.txt');
//                    Log::writeLog("短信发送失败|订单号[$r]|错误代码[{$sms_ret}]", Log::ERROR_LOG_PATH);
                    $this->errHandle("短信发送失败[{$sms_ret}]", $r);
                }
            }
            if (!$smsSendWithOrder || $smsSendAfterOrder) {
                //TODO::发送短信给供应商
                if ($p_info['p_type'] == 'C') {
                    $smsManual->SmsToApplyErHotel($ordername,
                        $p_info['ltitle'] . $p_info['ttitle'],
                        $tnum, $begintime, $endtime, $r, $option['memo']);
                } else {
                    self::log_result('发送供应商短信通知', '/var/www/html/new/d/logs/debug.txt');
                    $smsManual->OrderNotify('AFTER_SUBMIT', $proInfos, $ordername,
                        $r, $ordertel, $option['memo']);
                }
            }
            /*记录订单额外信息*/
            $this->appendInfo($r, $option);
            return array('orderNum' => $r, 'orderType' => $orderType, 'sendRut' => $sendRut);
        } else {
            $this->errHandle("下单接口出错", $r);
        }
    }

    /**
     *联票产品下单函数.
     *完成联票产品的下单,并更新uu_order_fx_details里的订单主从关系s信息.
     *@param array 联票产品下单信息数组
     *@param int r 主订单号，用来标识附属哪个订单
     */
    public function subOrder($c_infos,$r,$remoteorder='',$assembly = '',$series='' ){
        $str="update uu_order_fx_details set concat_id='$r' where orderid='$r' limit 1";
        $GLOBALS['le']->query($str);

        foreach($c_infos as $row){

            $c_r=$this->s->Group_Order_Submit($row['member'],$row['lid'],
                $row['tid'],$row['begintime'],$row['endtime'],$row['tprice'],
                $row['tnum'],0,$row['ordername'],$row['ordertel'],
                $row['contacttel'],$row['salerid'],$row['sapply_did'],
                $row['paymode'],$row['ordermode'],$remoteorder,$assembly,
                $series,"1","$r",0,$row['sfz']);
            if($c_r>=100000){
                $str="update uu_order_fx_details set concat_id='$r' where orderid='$c_r'";
                $GLOBALS['le']->query($str);
            }else{

                $this->errHandle("附属产品22下单出错".json_encode($row),$c_r);
            }
        }
    }

    /**
     * 下单给供应商发送短信
     *
     * @param int $mid 分销商ID
     * @param array $proInfos
     * @return bool
     */
    public function SendSmsToApplyer($mid, Array $proInfos)
    {
        $titles = $pids = array();
        foreach ($proInfos as $prod) {
            $pids[] = $prod['pid'];
            $mids[] = $prod['member'];
            $titles[$prod['pid']] = "{$prod['ltitle']}-{$prod['ttitle']}{$prod['tnum']}张,";
        }
        //查看哪些产品需要发送短信给供应商
        $sql = "SELECT f.pid,f.confirm_sms,l.fax,l.apply_did FROM uu_land_f f LEFT JOIN uu_land l"
            . " ON l.id=f.lid WHERE f.pid IN(".implode(',', $pids).")";
        $GLOBALS['le']->query($sql);
        $rows = array();
        $apply_did = 0;
        while( $row = $GLOBALS['le']->fetch_assoc() ){
            if ($row['confirm_sms']==1 && $row['fax']) {
                $rows[$row['fax']]['txt'] .= $titles[$row['pid']];
                $apply_did = $row['apply_did'];
            }
        }
        $mobiles = array_keys($rows);
        $cnt = count($mobiles);
        if (!class_exists('Log')) {
            include 'Log.class.php';
        }
        $logTime = date('Y-m-d H:i:s');
        if (!$cnt) {
            return false;
        }

        //获取分销商名称
        $sqlDname = "SELECT id,dname,fee_sms FROM pft_member"
            ." WHERE id IN($mid,$apply_did) LIMIT 2";
        $GLOBALS['le']->query($sqlDname);
        while($row=$GLOBALS['le']->fetch_assoc()) {
            if($row['id']==$mid) {
                $dname = $row['dname'];
            }
            elseif($row['id']==$apply_did) {
                $fee_sms  = $row['fee_sms'];
                $app_name = $row['dname'];
            }
        }
        $msg = "客户{$dname}预定了";
        //短信扣费
        $smsCnt = count($mobiles);
        $sms_money_total = $fee_sms * $smsCnt;
        $kq_r = $this->s->PFT_Member_Fund_Modify($apply_did, $apply_did,
            $sms_money_total, 1, 0, '', 8, 0);
        $cut_money_log = $logTime . "|供应商下单短信通知扣费|供应商{$app_name}"
            ."({$apply_did}),金额：{$sms_money_total}分,接口返回：{$kq_r}";
        \pft\Log\Log::writeLog( $cut_money_log ,
            '/var/www/html/new/d/logs/order_sms_2_applyer.log');
        if ($kq_r!==100) {
            return false;
        }
        foreach ($mobiles as $mobile) {
            $sms = $msg . substr_replace($rows[$mobile]['txt'], '。', -1). '【票付通】' ;
            $ret = $this->s->Send_SMS_G($mobile, $sms);
            \pft\Log\Log::writeLog($logTime. '|modile=' .$mobile
                .'sms='.$sms . 'ret=' . $ret ,
                '/var/www/html/new/d/logs/order_sms_2_applyer.log');
        }
        return true;
    }

    /**
     *套票产品下单函数.
     *票付通平台暂不支持.
     *@todo 如果要改为支持套票下单，完成测试工作，下函数未测试，是搬分销平台的.
     *@param array $order_infos 套票产品下单信息
     *@param int $r 套票产品下单主单号，需传如套票下单接口
     */
    public function appendOrder($order_infos,$r){
        $record=array("order"=>$r,"datetime"=>date("Y-m-d H:i:s"),"data"=>$order_infos);
        $recordStr=serialize($record);
        $errMsg=$r."套票附属产品下单失败";
        $acount=count($order_infos);
        $a_infos=array();
        foreach($order_infos as $row){
            $a_infos[$row['lid']][]=$row;
        }
        $ifpack=1;
        $xml=$this->s->Order_Globle_Search("","","","","","","","","","","","",
            $r,"","","","","",1,1,0,999,0,$stype,$payinfo,$pmode,$remotenum,
            $origin,$p_type,$order_confirm,$aid,$concat,$ifpack);
        $simplexml=simplexml_load_string($xml);
        $hasTidOrders=array();
        foreach($simplexml as $row){
            $hasTidOrders[(string)$row->UUtid]=(string)$row->UUordernum;
        }
        $count=count($simplexml);
        if($acount==($count-1)){//已下单
            return true;
        }elseif($count-1>0){//只下部分订单,进行补单
            $msg=$r."补单，套票附属订单数:".$acount.",实际下单数:".($count-1);
            $this->log_result($msg);
        }
        try{
            foreach($a_infos as $lid=>$aa_infos){
                $row=$aa_infos[0];
                if(array_key_exists($row['tid'],$hasTidOrders)){//该主单已经下成功
                    $ar=$hasTidOrders[$row['tid']];
                }else{
                    $ar=$this->s->Group_Order_Submit($row['member'],
                        $row['lid'],$row['tid'],$row['begintime'],
                        $row['endtime'],$row['tprice'],$row['tnum'],
                        0,$row['ordername'],$row['ordertel'],
                        $row['contacttel'],$row['salerid'],
                        $row['apply_did'],$row['paymode'],
                        $row['ordermode'],$remoteorder,
                        $assembly,$series,1,"0",$r);
                }
                if($ar>0&&$ar<100000){
                    $this->log_result($errMsg." outcome:".$ar);
                    return false;
                }
                for($i=1;$i<count($aa_infos);$i++){
                    $row=$aa_infos[$i];
                    if(array_key_exists($row['tid'],$hasTidOrders)){//该主单已经下成功
                        $c_ar=$hasTidOrders[$row['tid']];
                    }else{
                        $c_ar=$this->s->Group_Order_Submit($row['member'],
                            $row['lid'],$row['tid'],$row['begintime'],
                            $row['endtime'],$row['tprice'],$row['tnum'],
                            0,$row['ordername'],$row['ordertel'],
                            $row['contacttel'],$row['salerid'],
                            $row['apply_did'],$row['paymode'],
                            $row['ordermode'],$remoteorder,
                            $assembly,$series,1,"$ar",$r);
                    }
                    if($c_ar>100000||$ar<0){
                        $str="update uu_order_fx_details set concat_id='$ar' where orderid='$c_ar'";
                        $GLOBALS['le']->query($str);
                    }else{//套票下失败记录日志
                        $this->log_result($errMsg." outcome:".$c_ar);
                        return false;
                    }
                    if($i==count($aa_infos)-1){
                        $str="update uu_order_fx_details set concat_id='$ar' where orderid='$ar' limit 1";
                        $GLOBALS['le']->query($str);
                    }
                }
            }
        }catch(Exception $e){
            $this->log_result($errMsg." outcome:".$e->getMessage());
        }
    }

    /**
     *下单参数验证函数.
     *查看所传入参数是否合法
     *@param array $option 下单参数
     *@param array $p_info 产品信息
     *@throws DisOrderException
     */
    public function orderCheck($option,$p_info){
        $ptitle=$p_info['title'].$p_info['ttitle'];
        $tnum=$option['tnum'];
        $begintime=$option['begintime'];
        if($p_info['buy_limit_low']>0&&$tnum<$p_info['buy_limit_low']){
            throw new DisOrderException($ptitle."购买数少于购买下限".$p_info['buy_limit_low']);
        }
        if($p_info['buy_limit_up']>0&&$tnum>$p_info['buy_limit_up']){
            throw new DisOrderException("购买数不能多于购买上限");
        }
        if($p_info['p_status']==1||$p_info['p_status']==6){ throw new DisOrderException($ptitle."已删除或已下架"); }
        if(isset($option['sfz'])){
            $sfz=$option['sfz'];
            if(strlen($option['sfz'])==15){$sfz=$this->idcard_15to18($sfz);}
            if(!$this->idcard_checksum18($sfz)){throw new DisOrderException("身份证格式不正确");}
        }

        $minbegintime=strtotime("+".$p_info['ddays']." days");
        $minbegintime=date("Y-m-d",$minbegintime);

        if($begintime<$minbegintime){
            throw new DisOrderException($ptitle."游玩日期不能小于 $minbegintime");
        }
        if(($begintime==$minbegintime)&&$p_info['dhour']&&date("H:i:s")>$p_info['dhour']){
            throw new DisOrderException($ptitle."您需要在".$p_info['dhour']."前预订");
        }
    }


    /**
     * 分销权限查看函数.
     *
     * @param $proInfos 所有下单产品信息
     * @param $aid      上级供应商ID
     * @throws DisOrderException
     */
    public function authCheck($proInfos,$aid){

        foreach($proInfos as $row){
            $p=new ProductInfo($s,$row['pid'],$row['sapply_did']);
            if(!$p->supply($row['member'], $aid)){
                $pinfo=$p->pInfo();
                throw new DisOrderException("您无权限分销 ".$pinfo['ltitle']."(".$pinfo['ttitle'].")");
            }
        }
    }

    /**
     *支付验证函数.
     *查看用户是否有足够余额完成支付，和支付方式的验证.
     *@param int  $totalMoney 总金额
     *@throws DisOrderException
     */
    public function payCheck($totalMoney){
        $paymode=$this->option['paymode'];

        if($paymode==0){//账户余额
            if($this->m->money()<$totalMoney)
                throw new DisOrderException("账户余额不足!");
        }elseif($paymode==1){//支付宝
            return true;
        }elseif($paymode==2){//供应余额
            $pinfo=$this->p->pInfo();
            $aid=$pinfo['sapply_did'];
            if($this->m->tmoney($aid)<$totalMoney)
                throw new DisOrderException("供应余额不足!");
        }elseif($paymode==3){
            $pinfo=$this->p->pInfo();
            if($pinfo['apply_did']!=$this->m->memberID){
                throw new DisOrderException("产品非你供应，无法自我分销!");
            }
        }elseif($paymode==4){
            return true;
        }else{
            throw new DisOrderException("支付方式异常!");
        }
    }

    /**
     *产品库存验证函数.
     *查看产品是否有足够库存
     *@param array  $proInfos 所有下单产品信息
     *@throws DisOrderException
     */
    public function storageCheck($proInfos){
        $s=$this->s;
        foreach($proInfos as $row){
            if($row['storage']!=-1){//总库存
                $storageXml=$s->Dynamic_Storage_Check($row['tid'],2,NULL,$row['storage_open']);
                $storageXml=simplexml_load_string($storageXml);
                $sales=$storageXml->Rec->UUXstr;
                $remain=$row['storage']-$sales;
                if($row['tnum']>$remain){
                    throw new DisOrderException($row['ltitle'].$row['ttitle']." 剩余总库存数不足，剩余 $remain 张门票 $r");
                }
            }
            $pstorage=$s->get_Dynamic_Price_Merge($row['pid'],substr($row['begintime'],0,10),1,"","",0,1);
            $pstorage=explode(",",$pstorage);
            $pstorage=$pstorage[1];
            if($pstorage!=-1){//日库存
                $dayxml=$s->Dynamic_Storage_Check($row['tid'],1,substr($row['begintime'],0,10));
                $dayxml=simplexml_load_string($dayxml);
                $dayxml=(string)$dayxml->Rec->UUXstr;
                $dayxml=explode("|",$dayxml);
                $remain=$pstorage-$dayxml[1];
                if($row['tnum']>$remain){
                    throw new DisOrderException(substr($row['begintime'],0,10)." ".$row['ltitle'].$row['ttitle']."日库存数不足，剩余 $remain 张门票");
                }
            }
        }
    }

    /**
     *订单额外信息记录函数.
     *记录额外信息，如备注，到店时间，游客信息(姓名和身份证号)
     *@param int $r 订单号
     *@param array $option 包含产品额外信息
     */
    public function appendInfo($r,$option){
        $memo=$option['memo'];
        $origin=$option['origin'];
        if($memo||$origin){
            $str=$str="update uu_order_fx_details set memo='$memo',origin='$origin' where orderid='$r'";
            $GLOBALS['le']->query($str);
        }
        /*酒店到店时间*/
        if($arriveTime=mysql_real_escape_string($option['arriveTime'])){
            $str="update uu_order_fx_details set memo='最迟到店时间：$arriveTime' where orderid='$r' limit 1";
            $GLOBALS['le']->query($str);
        }
        /*记录订单游客信息*/
        $tourists=$option['tourists'];
        $idcards=$option['idcards'];
        if(count($tourists)>0){
            $str="insert into uu_order_tourist_info(orderid,tourist,idcard) values";
            for($i=0;$i<count($tourists);$i++){
                $str.="('".$r."','".$tourists[$i]."','".$idcards[$i]."'),";
            }
            $str=trim($str,",");
            $GLOBALS['le']->query($str);
        }
    }

    /**
     *获得套票产品附属产品下单信息.
     *@param string $attribute json数据，记录产品下单信息
     *@param array $param 下单参数
     *@return array 下单参数数组
     */
    public function aOrderInfo($attribute,$param){
        $attribute=json_decode($attribute,true);
        $tnum=$param['tnum'];
        $begintime=$param['begintime'];
        $endtime=$param['endtime'];
        $ordername=$param['ordername'];
        $ordertel=$param['ordertel'];
        $member=$param['member'];
        $paymode=$param['paymode'];
        $ordermode=$param['ordermode'];
        $a_infos=array();
        foreach($attribute as $row){//套票有效期判定
            $c_pid=$row['pid'];
            $c_tnum=$row['num'];
            $c_pro=new ProductInfo($c_pid,$this->s);
            $c_tprice=$c_pro->jsPrice($c_pid,$begintime);
            $c_about=$c_pro->pInfo();
            $array=array("member"=>$member,"tprice"=>$c_tprice,
                "tnum"=>$c_tnum*$tnum,"ltitle"=>$c_about['ltitle'],
                "ttitle"=>$c_about['ttitle'],"pid"=>$c_pid,
                "lid"=>$c_about['lid'],"tid"=>$c_about['tid'],
                "begintime"=>$begintime,"endtime"=>$endtime,
                "storage"=>$c_about['storage'],
                "storage_open"=>$c_about['storage_open'],
                "salerid"=>$c_about['salerid'],
                "apply_did"=>$c_about['apply_did'],
                "sapply_did"=>$c_about['sapply_did'],
                "ordername"=>$ordername,"ordertel"=>$ordertel,
                "paymode"=>$paymode,
                "ordermode"=>$ordermode);
            $a_infos[]=$array;
        }
        return $a_infos;
    }

    /**
     *错误处理函数.
     *抛出对应错误异常
     *@param string $msg 错误信息
     *@param int $code 错误代码
     *@throws Exception|MsgException|InterFaceException
     */
    public function errHandle($msg,$code){
        if($code>100000){
            throw new Exception("不存在大于100000的错误代码");
        }elseif($code<0){
            throw new MsgException($msg,$code);
        }else{
            throw new InterFaceException($msg,$code);
        }
    }

    /**
     *错误记录函数.
     *@param string $msg 错误信息
     *@param path 文件路径
     */
    public static function  log_result($msg,$path="/var/www/html/new/d/logs/log") {
        $fp = fopen($path,"a+");
        flock($fp, LOCK_EX) ;
        fwrite($fp,"执行日期：".date("Y-m-d H:i:s")."=>".$msg."\n");
        flock($fp, LOCK_UN);
        fclose($fp);
    }
}

/**
 *分销下单类
 *分销商分销
 */
class DisOrder extends OrderSubmit{
    public function __construct($s,$p,$m){
        parent::__construct($s,$p,$m,0,0);
    }
}

/**
 *零售下单类
 *产品以零售价销售，并分润给分销商，需第三方支付平台支持
 */
class SaleOrder extends OrderSubmit{
    public function __construct($s,$p,$m){
        parent::__construct($s,$p,$m,1,1);
    }
}
?>